/**
 * QUANSHI.com Inc.
 * Copyright (c) 2016-2017 All Rights Reserved.
 */
package com.quanshi.scheduler.core.utils;

import java.nio.charset.CharsetDecoder;
import java.util.Date;

import org.apache.commons.lang3.StringUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.serializer.SimpleDateFormatSerializer;

/**
 * FastJSON Utils
 * 
 * @author yanxiang.huang 2017-07-07 18:15:45
 */
public class FastJSONUtils {

    /** 序列化属性 */
    private static final SerializerFeature[] serializerFeatures   = { SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullListAsEmpty,
                                                                      SerializerFeature.WriteNullNumberAsZero, SerializerFeature.WriteNullBooleanAsFalse,
                                                                      SerializerFeature.WriteNullStringAsEmpty, SerializerFeature.SortField, SerializerFeature.SkipTransientField };

    /** 反序列化属性 */
    private static final Feature[]           deSerializerFeatures = { Feature.AllowUnQuotedFieldNames, Feature.AllowSingleQuotes, Feature.InternFieldNames,
                                                                      Feature.AllowArbitraryCommas, Feature.IgnoreNotMatch };

    /** 日期类型默认序列化格式 */
    private static final String              DEFAULT_DATE_FORMAT  = "yyyy-MM-dd HH:mm:ss.SSS";

    /** 序列化配置 */
    private static SerializeConfig           mapping              = new SerializeConfig();

    static {
        mapping.put(Date.class, new SimpleDateFormatSerializer(DEFAULT_DATE_FORMAT));
    }

    /**
     * java对象序列化为字符串
     * 
     * @param obj 待序列化的java对象
     * @return
     */
    public static String toJSONString(Object obj) {
        return toJSONString(obj, null);
    }

    /**
     * Java对象转换为JSON字符串
     * 
     * @param obj Java对象
     * @param dateFormat 日期格式
     * @return 序列化后的JSON字符串
     */
    public static String toJSONString(Object obj, String dateFormat) {
        if (StringUtils.isBlank(dateFormat)) {
            return JSON.toJSONString(obj, mapping, serializerFeatures);
        }
        return JSON.toJSONStringWithDateFormat(obj, dateFormat, serializerFeatures);
    }

    /**
     * Java对象转换为二进制数据
     * 
     * @param obj Java对象
     * @return 序列化后的JSON二进制数据
     */
    public static byte[] toJSONStringBytes(Object obj) {
        return toJSONStringBytes(obj, null);
    }

    /**
     * Java对象转换为二进制数据
     * 
     * @param obj Java对象
     * @param dateFormat 日期格式
     * @return 序列化后的JSON字符串
     */
    public static byte[] toJSONStringBytes(Object obj, String dateFormat) {
        if (!StringUtils.isBlank(dateFormat)) {
            mapping.put(Date.class, new SimpleDateFormatSerializer(dateFormat));
        }
        return JSON.toJSONBytes(obj, mapping, serializerFeatures);
    }

    /**
     * JSON字符串反序列化为Java对象
     * 
     * @param json JSON字符串
     * @param clazz 反序列化对象类型
     * @return 反序列化对象
     */
    public static <T> T fromJSONString(String json, Class<T> clazz) {
        return JSON.parseObject(json, clazz, deSerializerFeatures);
    }

    /**
     * JSON字符串反序列化为Java对象
     * 
     * @param json JSON字符串
     * @param ref 反序列化对象类型
     * @return 反序列化对象
     */
    public static <T> T fromJSONString(String json, TypeReference<T> ref) {
        return JSON.parseObject(json, ref, deSerializerFeatures);
    }

    /**
     * JSON二进制数据反序列化为Java对象
     * 
     * @param bytes JSON二进制数据
     * @param clazz 反序列化对象类型
     * @return 反序列化对象
     */
    public static <T> T fromJSONString(byte[] bytes, Class<T> clazz) {
        return JSON.<T> parseObject(bytes, clazz, deSerializerFeatures);
    }

    /**
     * JSON二进制数据反序列化为Java对象
     * 
     * @param bytes JSON二进制数据
     * @param clazz 反序列化对象类型
     * @param dateFormat 日期格式
     * @return 反序列化对象
     */
    public static <T> T fromJSONString(byte[] bytes, Class<T> clazz, String dateFormat) {
        return JSON.parseObject(bytes, clazz, deSerializerFeatures);
    }

    /**
     * JSON二进制数据反序列化为Java对象
     * 
     * @param bytes JSON二进制数据
     * @param off 二进制数据起始字节数组下标
     * @param len 需要反序列化二进制数据的长度
     * @param charsetDecoder 反序列化数据的字符编码类型
     * @param clazz 反序列化对象类型
     * @return 反序列化对象
     */
    public static <T> T fromJSONString(byte[] bytes, int off, int len, CharsetDecoder charsetDecoder, Class<T> clazz) {
        return JSON.<T> parseObject(bytes, off, len, charsetDecoder, clazz, deSerializerFeatures);
    }
}
